/*******************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.        */
/*                                                                 */
/*  NAME      = frreport_comm.c                                    */
/*  NOTE      = report_comm公用                                    */
/*  DATE      = 2014/12/23                                         */
/*******************************************************************/

#include <stdio.h>
#include <unistd.h>

#include "frsutl.h"
#include "frlog.h"

#include "frct_comm.h"
#include "frreport_comm.h"

/*******************************************************************************
*  FUNC     :  获取指定链表
*  ARGS     :  p_st_hash_report     (Frhash_header *; 保存Frreport_data)
*           :  ui_idx               (需要从hash里获取的连表位置)
*  RTN      :  Frlist_header *
*  NOTE     :
*******************************************************************************/
FR_STATIC Frlist_header *__frreport_get_report_hdr(Frhash_header  *p_st_hash_report  //保存Frreport_data
                                                  , unsigned int ui_idx )
{
    Frlist_header *p_st_lst_hdr_tmp = NULL;
    int i_loop=0;

    if(p_st_hash_report == NULL
       || (ui_idx != APM_REPORT_TYPE_L7DATA && ui_idx != APM_REPORT_TYPE_OTHER) )
        return NULL;

    FRHASH_LOOP(i_loop, p_st_hash_report, p_st_lst_hdr_tmp)
    {
        if(ui_idx == i_loop)
            return p_st_lst_hdr_tmp;
    }

    return NULL;
}

/*******************************************************************************
*  FUNC     :  节点data_field内存释放
*  ARGS     :  p_st_node  (Frlist_node *)
*  RTN      :
*  NOTE     :
*******************************************************************************/
FR_STATIC void __list_node_free_data_field(Frlist_node *p_st_node)
{
    Frdata_field *p_st_data_field;

    if(p_st_node==NULL || p_st_node->data == NULL )
        return;

    p_st_data_field = (Frdata_field *)FRLIST_GET_NODE_DATA(p_st_node);

    if(p_st_data_field->p_field_name)
        frfree(p_st_data_field->p_field_name);
    if(p_st_data_field->p_field_value)
        frfree(p_st_data_field->p_field_value);
    frfree(p_st_node->data);

    return;
}

/*******************************************************************************
*  FUNC     :  p_st_l7data_field内存释放
*  ARGS     :  p_st_data_field  (FRl7data_field *)
*  RTN      :
*  NOTE     :
*******************************************************************************/
void frreport_free_l7data_field(FRl7data_field **pp_st_l7data_field)
{
    FRl7data_field *p_st_l7data_field;

    if(pp_st_l7data_field == NULL || *pp_st_l7data_field == NULL)
        return;

    p_st_l7data_field = *pp_st_l7data_field;
    if(p_st_l7data_field->p_module_name)
        frfree(p_st_l7data_field->p_module_name);
    if(p_st_l7data_field->p_response_codestring)
        frfree(p_st_l7data_field->p_response_codestring);
    if(p_st_l7data_field->p_transaction_title)
        frfree(p_st_l7data_field->p_transaction_title);
    if(p_st_l7data_field->p_server_name)
        frfree(p_st_l7data_field->p_server_name);
    if(p_st_l7data_field->p_xml_fields)
        frfree(p_st_l7data_field->p_xml_fields);
    if(p_st_l7data_field->p_st_lst_request_data)
    {
        frlist_destroy(p_st_l7data_field->p_st_lst_request_data, __list_node_free_data_field);
        p_st_l7data_field->p_st_lst_request_data = NULL;
    }
    if(p_st_l7data_field->p_st_lst_response_data)
    {
        frlist_destroy(p_st_l7data_field->p_st_lst_response_data, __list_node_free_data_field);
        p_st_l7data_field->p_st_lst_response_data = NULL;
    }
    frfree(p_st_l7data_field);
    *pp_st_l7data_field = NULL;

    return;
}

/*******************************************************************************
*  FUNC     :  获取保存l7data的report_data，如果没有查询到，生成为l7data用的新report_data
*  ARGS     :  p_st_list_report     (Frlist_header*; 保存Frreport_data)
*           :  p_st_trans_info      (Frlist_header*)
*           :  i_use_request        (当前数据是否request)
*           :  i_use_response       (当前数据是否response)
*           :  p_i_flag_new         (返回值!=NULL,有效;FR_YES:新建Frreport_data, FR_NO:不是新建连接)
*  RTN      :  Frreport_data *
*  NOTE     :
*******************************************************************************/
FR_STATIC Frreport_data *__frreport_get_report_data(Frlist_header *p_st_list_report
                                                  , Frtrans_info  *p_st_trans_info
                                                  , int i_use_request
                                                  , int i_use_response
                                                  , int *p_i_flag_new
                                                   )
{
    Frreport_data *p_st_report=NULL, *p_st_report_tmp=NULL;
    Frlist_node *p_st_node=NULL;
    Frreport_l7data  *p_st_l7data=NULL;

    if(p_st_list_report == NULL || p_st_trans_info==NULL || p_i_flag_new==NULL )
        return NULL;

    p_st_node = FRLIST_FIRST_NODE(p_st_list_report);
    while(p_st_node)
    {
        p_st_report_tmp =  (Frreport_data*)FRLIST_GET_NODE_DATA(p_st_node);
        if(p_st_report_tmp == NULL || p_st_report_tmp->em_data_type != FRREPORT_TYPE_DATA )
        {
            p_st_node = FRLIST_NEXT_NODE(p_st_node);
            continue;
        }
        //根据数据包大小和request时间进行判断
        p_st_l7data = &p_st_report_tmp->un_data.st_l7data;
        if(i_use_request == FR_YES
           && p_st_l7data->l_request_bytes == p_st_trans_info->st_l4_trans.l_request_bytes
           && p_st_l7data->st_request_time.tv_sec == p_st_trans_info->st_l4_trans.st_request_time.tv_sec
           && p_st_l7data->st_request_time.tv_usec == p_st_trans_info->st_l4_trans.st_request_time.tv_usec)
        {
            p_st_report = p_st_report_tmp;
            break;
        }
        //根据数据包大小和response时间进行判断
        if(i_use_response == FR_YES
           && p_st_l7data->l_response_bytes == p_st_trans_info->st_l4_trans.l_response_bytes
           && p_st_l7data->st_response_time.tv_sec == p_st_trans_info->st_l4_trans.st_response_time.tv_sec
           && p_st_l7data->st_response_time.tv_usec == p_st_trans_info->st_l4_trans.st_response_time.tv_usec)
        {
            p_st_report = p_st_report_tmp;
            break;
        }
        p_st_node = FRLIST_NEXT_NODE(p_st_node);
    }

    if(p_st_report)
    {
        *p_i_flag_new = FR_NO;
        return p_st_report;
    }
    //生成新的report_data,并初始化
    *p_i_flag_new = FR_YES;
    p_st_report = frmalloc(sizeof(Frreport_data));
    if(p_st_report == NULL)
    {
        FRLOG_ERROR_DETAIL("frmalloc err");
        return NULL;
    }
    memset(p_st_report, 0x00, sizeof(Frreport_data));
    p_st_report->em_data_type = FRREPORT_TYPE_DATA;
    frlist_header_init(&p_st_report->un_data.st_l7data.st_lst_l7data);

    p_st_node = frlist_node_create(p_st_report);
    if(p_st_node==NULL)
    {
        FRLOG_ERROR_DETAIL("frmalloc err");
        frfree(p_st_report);
        return NULL;
    }
    frlist_push(p_st_list_report, p_st_node);

    return p_st_report;
}

/*******************************************************************************
*  FUNC     :  获取保存l7data的report_data，如果没有查询到，生成为l7data用的新report_data
*  ARGS     :  i_l7_proto               (l7 协议号)
*           :  p_module_name            (模块名)
*           :  l_response_code          (应答的状态码;如果是request,设置为0)
*           :  p_response_codestring    (应答的状态码串;如果是request,设置为NULL)
*           :  p_transaction_title      (标识符。NULL表示没有)
*           :  p_server_name            (检查到的服务器名称)
*           :  p_st_lst_request_data    (请求的所有参数列表)
*           :  p_st_lst_response_data   (应答结果列表;如果是request,设置为NULL)
*  RTN      :  Frreport_data *
*  NOTE     :
*******************************************************************************/
FR_STATIC Frlist_node*__frreport_mk_FRl7data_field(int i_l7_proto
                                                  , char *p_module_name
                                                  , long  l_response_code
                                                  , char *p_response_codestring
                                                  , char *p_transaction_title
                                                  , char *p_server_name
                                                  , int   i_batch_count
                                                  , char *p_xml_fields
                                                  , Frlist_header *p_st_lst_request_data
                                                  , Frlist_header *p_st_lst_response_data)
{
    FRl7data_field *p_st_l7data_field=NULL;
    Frlist_node *p_st_node=NULL;

    p_st_l7data_field = frmalloc(sizeof(FRl7data_field));
    if(p_st_l7data_field == NULL)
    {
        FRLOG_ERROR_DETAIL("frmalloc err");
        return NULL;
    }
    memset(p_st_l7data_field, 0x00, sizeof(FRl7data_field));

    p_st_l7data_field->i_l7_proto = i_l7_proto;
    if(p_module_name)
        p_st_l7data_field->p_module_name = frstrdup(p_module_name);
    p_st_l7data_field->l_response_code = l_response_code;
    if(p_response_codestring)
        p_st_l7data_field->p_response_codestring = frstrdup(p_response_codestring);

    //查询关键字
    if(p_transaction_title)
        p_st_l7data_field->p_transaction_title = frstrdup(p_transaction_title);
    if(p_server_name)
        p_st_l7data_field->p_server_name = frstrdup(p_server_name);

    p_st_l7data_field->i_batch_count = i_batch_count;
    if(p_xml_fields)
        p_st_l7data_field->p_xml_fields = frstrdup(p_xml_fields);
    else
        p_st_l7data_field->p_xml_fields = NULL;

    p_st_l7data_field->p_st_lst_request_data = p_st_lst_request_data;
    p_st_l7data_field->p_st_lst_response_data = p_st_lst_response_data;
    p_st_node = frlist_node_create(p_st_l7data_field);
    if(p_st_node == NULL)
    {
        frreport_free_l7data_field(&p_st_l7data_field);
        FRLOG_ERROR_DETAIL("frlist_node_create err");
    }
    return p_st_node;
}

/*******************************************************************************
*  FUNC     :  保存l7 data 数据到链表
*  ARGS     :  p_st_hash_report     (Frhash_header *; 数据保存到hash)
*           :  p_st_ct              (Conntrack *)
*           ：  p_st_trans_info      (p_st_trans_info 协议分析释放)
*           :  i_use_request        (当前数据是 request)
*           :  i_response_required  (0:不期待响应数据,1:有response数据)
*           :  i_use_response       (当前数据是 response)
*           :  p_st_lst_hdr_req     (Frlist_header *;p_st_lst_hdr_req和里面的数据Frdata_field,由框架(apm)释放)
*           :  p_st_lst_hdr_resp    (Frlist_header *;p_st_lst_hdr_resp和里面的数据Frdata_field,由框架(apm)释放)
*  RTN      :  成功:FR_SUCC; 失败:FR_FAIL
*  NOTE     :
*******************************************************************************/
int frreport_add_l7data( Frhash_header *p_st_hash_report
                       , Conntrack     *p_st_ct
                       , Frtrans_info  *p_st_trans_info
                       , int i_use_request
                       , int i_response_required
                       , int i_use_response
                       , Frlist_header *p_st_lst_hdr_req
                       , Frlist_header *p_st_lst_hdr_resp )
{
    L7_analyzer *p_st_l7_analyzer=NULL;
    Frlist_header *p_st_lst_hdr_report = NULL;
    Frreport_data *p_st_report_data=NULL;
    Frreport_l7data *p_st_report_l7data=NULL;
    Frlist_node *p_st_node=NULL;
    int i_flag_new=FR_NO;

    //入力参数检查
    if(p_st_hash_report == NULL
       || p_st_ct == NULL
       || p_st_trans_info == NULL)
        return FR_FAIL;

    //获取协议信息
    p_st_l7_analyzer = frproto_l7_get_analyzer(p_st_ct);
    if(p_st_l7_analyzer == NULL || p_st_l7_analyzer->p_st_l7_module == NULL || p_st_l7_analyzer->p_st_session == NULL)
    {
        FRLOG_WARN_DETAIL("frproto_l7_get_analyzer NULL");
        return FR_FAIL;
    }

    //获取report_data
    p_st_lst_hdr_report = __frreport_get_report_hdr(p_st_hash_report, APM_REPORT_TYPE_L7DATA);
    if(p_st_lst_hdr_report == NULL)
    {
        FRLOG_WARN_DETAIL("lst_hdr_report NULL");
        return FR_FAIL;
    }

    p_st_report_data =__frreport_get_report_data(p_st_lst_hdr_report, p_st_trans_info, i_use_request, i_use_response, &i_flag_new);
    if(p_st_report_data == NULL)
    {
        FRLOG_WARN_DETAIL("p_st_report_data NULL");
        return FR_FAIL;
    }

    p_st_report_l7data = &p_st_report_data->un_data.st_l7data;
    //如果是新增加协议，设置基础信息
    if(i_flag_new == FR_YES)
    {
        memcpy(p_st_report_l7data->arr_session_id, p_st_l7_analyzer->p_st_session->arr_session_id, APM_UUID_SIZE);
        memcpy(p_st_report_l7data->arr_connection_id, p_st_ct->arr_connection_id, APM_UUID_SIZE);
        p_st_report_l7data->ip_proto = p_st_ct->ip_proto;
        memcpy(p_st_report_l7data->src_mac, p_st_ct->src_mac, APM_MAC_SIZE);
        p_st_report_l7data->src_ip = p_st_ct->src_ip;
        p_st_report_l7data->src_port = p_st_ct->src_port;
        p_st_report_l7data->dst_ip = p_st_ct->dst_ip;
        p_st_report_l7data->dst_port = p_st_ct->dst_port;
        //request 数据
        p_st_report_l7data->i_use_request = i_use_request;
        if(i_use_request == FR_YES)
        {
            p_st_report_l7data->st_request_time = p_st_trans_info->st_l4_trans.st_request_time;
            p_st_report_l7data->l_request_bytes = p_st_trans_info->st_l4_trans.l_request_bytes;
            if(p_st_trans_info->st_l7_trans.p_transaction_code)
                p_st_report_l7data->p_transaction_code = frstrdup(p_st_trans_info->st_l7_trans.p_transaction_code);
            else
                p_st_report_l7data->p_transaction_code = NULL;
            if(p_st_trans_info->st_l7_trans.p_transaction_title)
                p_st_report_l7data->p_transaction_title = frstrdup(p_st_trans_info->st_l7_trans.p_transaction_title);
            else
                p_st_report_l7data->p_transaction_title = NULL;
            p_st_report_l7data->i_response_required = i_response_required;
        }

        //response数据
        p_st_report_l7data->i_use_response = i_use_response;
        if(i_use_response == FR_YES)
        {
            p_st_report_l7data->l_response_code = p_st_trans_info->st_l7_trans.l_response_code;
            if(p_st_trans_info->st_l7_trans.p_response_codestring)
                p_st_report_l7data->p_response_codestring = frstrdup(p_st_trans_info->st_l7_trans.p_response_codestring);
            else
                p_st_report_l7data->p_response_codestring = NULL;

            p_st_report_l7data->l_response_bytes = p_st_trans_info->st_l4_trans.l_response_bytes;
            p_st_report_l7data->st_response_time_first_byte = p_st_trans_info->st_l4_trans.st_response_time_first_byte;
            p_st_report_l7data->st_response_time = p_st_trans_info->st_l4_trans.st_response_time;

            p_st_report_l7data->ul_response_time_firstbyte_us =p_st_trans_info->st_l4_trans.ul_response_time_firstbyte_us;
            p_st_report_l7data->ul_response_time_us =p_st_trans_info->st_l4_trans.ul_response_time_us;
        }
    }

    //数据加入到链表
    p_st_node = __frreport_mk_FRl7data_field(p_st_l7_analyzer->p_st_l7_module->i_l7_proto
                                        , p_st_l7_analyzer->p_st_l7_module->p_module_name
                                        , i_use_response == FR_YES ? p_st_trans_info->st_l7_trans.l_response_code:0
                                        , i_use_response == FR_YES ? p_st_trans_info->st_l7_trans.p_response_codestring:NULL
                                        , p_st_trans_info->st_l7_trans.p_transaction_title
                                        , p_st_trans_info->st_l7_trans.p_server_name
                                        , i_use_request == FR_YES?p_st_trans_info->st_l7_trans.i_batch_count:0
                                        , i_use_response == FR_YES?p_st_trans_info->st_l7_trans.p_xml_fields:NULL
                                        , p_st_lst_hdr_req, p_st_lst_hdr_resp);
    frlist_push(&p_st_report_l7data->st_lst_l7data, p_st_node);

    //如果当前协议的层数与要保存的节点层数不一致,报警输出
    if( frlist_size(&p_st_report_l7data->st_lst_l7data) != p_st_ct->i_active_l7proto_idx +1 )
        FRLOG_WARN_DETAIL("save position incorrect(l7data position%d active_proto_idx=%d)"
                    , frlist_size(&p_st_report_l7data->st_lst_l7data)
                    , p_st_ct->i_active_l7proto_idx +1);

    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  保存session 数据到链表
*  ARGS     :  p_st_hash_report (Frhash_header *; 数据保存到hash)
*           :  p_st_ct          (Conntrack *)
*           :  st_timestamp     (数据发生时间)
*           :  p_st_lst_session_data    (Frlist_header *; session数据;
*           :                    p_st_lst_session_data和里面的数据Frdata_field,由apm进行释放)
*           :  i_status         (用户登录 / 用户退出)
*  RTN      :  成功:FR_SUCC; 失败:FR_FAIL
*  NOTE     :
*******************************************************************************/
int frreport_add_session_data(Frhash_header *p_st_hash_report   //保存Frreport_data
                              , Conntrack *p_st_ct
                              , struct timeval st_timestamp
                              , Frlist_header *p_st_lst_session_data
                              , int i_status
                              )
{
    L7_analyzer *p_st_l7_analyzer=NULL;
    Frlist_header *p_st_lst_hdr_report = NULL;
    Frreport_data *p_st_report_data=NULL;
    Frreport_session *p_st_session=NULL;
    Frlist_node *p_st_node=NULL;

    //入力参数检查
    if(p_st_hash_report == NULL || p_st_ct == NULL)
        return FR_FAIL;

    //获取协议信息
    p_st_l7_analyzer = frproto_l7_get_analyzer(p_st_ct);
    if(p_st_l7_analyzer == NULL || p_st_l7_analyzer->p_st_l7_module == NULL || p_st_l7_analyzer->p_st_session == NULL)
    {
        FRLOG_WARN_DETAIL("frproto_l7_get_analyzer NULL");
        return FR_FAIL;
    }

    //获取report_data
    p_st_lst_hdr_report = __frreport_get_report_hdr(p_st_hash_report, APM_REPORT_TYPE_OTHER);
    if(p_st_lst_hdr_report == NULL)
    {
        FRLOG_WARN_DETAIL("lst_hdr_report NULL");
        return FR_FAIL;
    }

    //生成新的report_data,并初始化
    p_st_report_data = frmalloc(sizeof(Frreport_data));
    if(p_st_report_data == NULL)
    {
        FRLOG_ERROR_DETAIL("frmalloc err");
        return FR_FAIL;
    }
    p_st_node = frlist_node_create(p_st_report_data);
    if(p_st_node==NULL)
    {
        FRLOG_ERROR_DETAIL("frlist_node_create err");
        frfree(p_st_report_data);
        return FR_FAIL;
    }
    frlist_push(p_st_lst_hdr_report, p_st_node);

    memset(p_st_report_data, 0x00, sizeof(Frreport_data));
    p_st_report_data->em_data_type = FRREPORT_TYPE_SESSION;
    p_st_session = &p_st_report_data->un_data.st_session;

    //赋值
    memcpy(p_st_session->arr_session_id, p_st_l7_analyzer->p_st_session->arr_session_id, APM_UUID_SIZE);
    memcpy(p_st_session->arr_connection_id, p_st_ct->arr_connection_id, APM_UUID_SIZE);
    p_st_session->ip_proto = p_st_ct->ip_proto;
    memcpy(p_st_session->src_mac, p_st_ct->src_mac, APM_MAC_SIZE);
    p_st_session->src_ip = p_st_ct->src_ip;
    p_st_session->src_port = p_st_ct->src_port;
    p_st_session->dst_ip = p_st_ct->dst_ip;
    p_st_session->dst_port = p_st_ct->dst_port;

    if(p_st_l7_analyzer->p_st_session->p_username)
        p_st_session->p_username = frstrdup(p_st_l7_analyzer->p_st_session->p_username);
    else
        p_st_session->p_username = NULL;
    p_st_session->i_status = i_status;
    p_st_session->st_timestamp = st_timestamp;
    p_st_session->p_st_lst_session_data = p_st_lst_session_data;

    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  保存关联连接信息
*  ARGS     :  p_st_hash_report (Frhash_header *; 数据保存到hash)
*           :  p_st_ct          (Conntrack *)
*           :  ip_proto         (IPPROTO_TCP/IPPROTO_UDP)
*           :  src_ip           (原ip)
*           :  dst_ip           (目的ip)
*           :  dst_port         (目的port)
*           :  ui_redirect_ip   (重定向ip)
*           :  us_redirect_port (重定向port)
*           :  st_timestamp     (数据发生时间)
*  RTN      :  成功:FR_SUCC; 失败:FR_FAIL
*  NOTE     :
*******************************************************************************/
int frreport_add_conn_expect(Frhash_header *p_st_hash_report
                             , u_short ip_proto
                             , u_int src_ip
                             , u_int dst_ip
                             , u_short dst_port
                             , u_int   ui_redirect_ip
                             , u_short us_redirect_port
                             , struct timeval st_timestamp
                             )
{
    Frlist_header *p_st_lst_hdr_report = NULL;
    Frreport_data *p_st_report_data=NULL;
    Frreport_conn_expect *p_st_conn_expect=NULL;
    Frlist_node *p_st_node=NULL;

    //入力参数检查
    if(p_st_hash_report == NULL)
        return FR_FAIL;

    //获取report_data
    p_st_lst_hdr_report = __frreport_get_report_hdr(p_st_hash_report, APM_REPORT_TYPE_OTHER);
    if(p_st_lst_hdr_report == NULL)
    {
        FRLOG_WARN_DETAIL("lst_hdr_report NULL");
        return FR_FAIL;
    }

    //生成新的report_data,并初始化
    p_st_report_data = frmalloc(sizeof(Frreport_data));
    if(p_st_report_data == NULL)
    {
        FRLOG_ERROR_DETAIL("frmalloc err");
        return FR_FAIL;
    }
    p_st_node = frlist_node_create(p_st_report_data);
    if(p_st_node==NULL)
    {
        FRLOG_ERROR_DETAIL("frlist_node_create err");
        frfree(p_st_report_data);
        return FR_FAIL;
    }
    frlist_push(p_st_lst_hdr_report, p_st_node);

    memset(p_st_report_data, 0x00, sizeof(Frreport_data));
    p_st_report_data->em_data_type = FRREPORT_TYPE_CONN_EXPECT;
    p_st_conn_expect = &p_st_report_data->un_data.st_conn_expect;

    //赋值
    p_st_conn_expect->ip_proto = ip_proto;
    memset(p_st_conn_expect->src_mac, 0x00, APM_MAC_SIZE);
    p_st_conn_expect->src_ip = src_ip;
    p_st_conn_expect->src_port = 0;
    p_st_conn_expect->dst_ip = dst_ip;
    p_st_conn_expect->dst_port = dst_port;

    p_st_conn_expect->redirect_ip = ui_redirect_ip;
    p_st_conn_expect->redirect_port = us_redirect_port;

    p_st_conn_expect->st_timestamp = st_timestamp;

    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  释放Frtrans_info变量内存
*  ARGS     :  p_st_trans_info     (Frtrans_info *)
*  RTN      :
*  NOTE     :
*******************************************************************************/
void frreport_free_trans_info(Frtrans_info *p_st_trans_info)
{
    if(p_st_trans_info == NULL)
        return;

    if(p_st_trans_info->st_l7_trans.p_transaction_code)
    {
        frfree(p_st_trans_info->st_l7_trans.p_transaction_code);
        p_st_trans_info->st_l7_trans.p_transaction_code = NULL;
    }
    if(p_st_trans_info->st_l7_trans.p_transaction_title)
    {
        frfree(p_st_trans_info->st_l7_trans.p_transaction_title);
        p_st_trans_info->st_l7_trans.p_transaction_title = NULL;
    }
    if(p_st_trans_info->st_l7_trans.p_response_codestring)
    {
        frfree(p_st_trans_info->st_l7_trans.p_response_codestring);
        p_st_trans_info->st_l7_trans.p_response_codestring = NULL;
    }

    return;
}
